import { App, computed, defineComponent, onMounted, ref, toRef, watch } from "vue";

import hljs from 'highlight.js/lib/core'
import { HighlightResult } from 'highlight.js';
import xml from 'highlight.js/lib/languages/xml'
import javascript from 'highlight.js/lib/languages/javascript'
import 'highlight.js/styles/atom-one-dark.css'

hljs.registerLanguage('javascript', javascript)
hljs.registerLanguage('html', xml)

const prefixCls = 'x-code' 

const Code = defineComponent({
  name: prefixCls,
  props: {
    code: String,
    language: String,
    trim: { default: true }
  },
  setup(props, { slots }) {

    const codeRef = ref<HTMLElement>()

    const resultRef = computed(() => {
      let code = props.code
      if (!code) return {} as HighlightResult
      if (props.trim) code = code.trim()
      if (props.language) {
        return hljs.highlight(code, { language: props.language, ignoreIllegals: true })
      } else {
        return hljs.highlightAuto(code)
      }
    })

    const languageRef = computed(() => resultRef.value.language || props.language)

    function setCode() {
      if (slots.default) return
      if (!codeRef.value) return
      codeRef.value.innerHTML = resultRef.value.value
    }

    onMounted(setCode)
    watch([toRef(props, 'code'), toRef(props, 'language')], setCode)

    return () => {
      const cls = [prefixCls]
      const language = languageRef.value
      return (
        <code class={['hljs ' + language, cls]}>
          { slots.default ? slots.default?.() : <pre ref={codeRef} /> }
        </code>
      )
    }
  }
})

Code.install = (app: App) => {
  app.component(Code.name, Code)
}

export default Code